﻿$currentScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path

# 定义配置文件路径
$configFilePath = Join-Path -Path $currentScriptPath -ChildPath "deploy.json"

# 默认值
$defaultAppDirName = "app"
$defaultPort = "8080"
$defaultEnvironment = "Production"

# 检查配置文件是否存在
if (-Not (Test-Path $configFilePath)) {
    # 手动输入配置信息，默认值已提供
    do {
        $downloadUrl = Read-Host "请输入部署包下载地址"
    } while ([string]::IsNullOrWhiteSpace($downloadUrl))

    # 提取 StartDllName 默认值
    $fileName = [System.IO.Path]::GetFileNameWithoutExtension($downloadUrl)
    if ($fileName.EndsWith(".latest")) {
        $fileName = $fileName -replace "\.latest", ""
    }
    $defaultStartDllName = "$fileName.dll"

    $startDllName = Read-Host "请输入应用启动dll名称 (默认: $defaultStartDllName)"
    if ([string]::IsNullOrWhiteSpace($startDllName)) {
        $startDllName = $defaultStartDllName
    }

    $appDirName = Read-Host "请输入应用目录名称 (默认: $defaultAppDirName)" -Default $defaultAppDirName
    if ([string]::IsNullOrWhiteSpace($appDirName)) {
        $appDirName = $defaultAppDirName
    }

    $port = Read-Host "请输入端口 (默认: $defaultPort)" -Default $defaultPort
    if ([string]::IsNullOrWhiteSpace($port)) {
        $port = $defaultPort
    }

    $environment = Read-Host "请输入环境变量 (默认: $defaultEnvironment)" -Default $defaultEnvironment
    if ([string]::IsNullOrWhiteSpace($environment)) {
        $environment = $defaultEnvironment
    }

    # 创建配置对象
    $config = @{
        DownloadUrl = $downloadUrl
        AppDirName = $appDirName
        StartDllName = $startDllName
        Port = $port
        Environment = $environment
    }

    # 将配置写入JSON文件，使用UTF-8 BOM编码
    if ($PSVersionTable.PSVersion.Major -ge 6) {
        ConvertTo-Json -InputObject $config | Out-File -FilePath $configFilePath -Encoding utf8BOM
    } else {
        $jsonContent = ConvertTo-Json -InputObject $config
        $bom = [byte[]]@(0xEF, 0xBB, 0xBF)
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($jsonContent)
        [System.IO.File]::WriteAllBytes($configFilePath, $bom + $bytes)
    }
} else {
    # 读取配置文件
    $config = Get-Content -Path $configFilePath | ConvertFrom-Json
}

$appDirectory = Join-Path -Path $currentScriptPath -ChildPath $config.AppDirName
$zipFileName = [System.IO.Path]::GetFileName($config.DownloadUrl)
$zipFilePath = Join-Path -Path $currentScriptPath -ChildPath $zipFileName

# 如果不存在应用目录，则检查是否有本地zip包，否则远程下载并解压部署包
if (-Not (Test-Path $appDirectory)) {
    if (Test-Path $zipFilePath) {
        Write-Output "找到本地部署包，正在解压..."
        Expand-Archive -Path $zipFilePath -DestinationPath $appDirectory
        Write-Output "部署包已成功解压到 $appDirectory"
    } else {
        Write-Output "应用目录不存在，正在下载部署包..."
        Invoke-WebRequest -Uri $config.DownloadUrl -OutFile $zipFilePath
        Expand-Archive -Path $zipFilePath -DestinationPath $appDirectory
        Write-Output "部署包已成功解压到 $appDirectory"
    }
}

$winswExePath = Join-Path -Path $currentScriptPath -ChildPath "winsw.exe"

# 如果winsw.exe不存在则下载
if (-Not (Test-Path $winswExePath)) {
    Write-Output "winsw.exe不存在，正在下载..."
    Invoke-WebRequest -Uri "https://soft-tools-runtime.oss-cn-chengdu.aliyuncs.com/winsw.exe" -OutFile $winswExePath
    Write-Output "winsw.exe已成功下载"
}

# 生成winsw.xml文件
$serviceName = [System.IO.Path]::GetFileNameWithoutExtension($config.StartDllName) -replace "\.dll", ""

$xmlContent = @"
<service>
  <id>$serviceName</id>
  <name>$serviceName Service</name>
  <description>This service runs the $serviceName application.</description>
  <executable>dotnet</executable>
  <arguments>$($config.StartDllName) --urls=http://*:$($config.Port)/ --environment $($config.Environment)</arguments>
  <logmode>rotate</logmode>
  <logpath>%BASE%\logs</logpath>
  <logsize>1M</logsize>
  <logfiles>10</logfiles>
  <workingdirectory>%BASE%\$($config.AppDirName)</workingdirectory>
</service>
"@

# 将XML内容写入文件，使用UTF-8 BOM编码
if ($PSVersionTable.PSVersion.Major -ge 6) {
    $xmlContent | Out-File -FilePath (Join-Path -Path $currentScriptPath -ChildPath "winsw.xml") -Encoding utf8BOM
} else {
    $bom = [byte[]]@(0xEF, 0xBB, 0xBF)
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($xmlContent)
    [System.IO.File]::WriteAllBytes((Join-Path -Path $currentScriptPath -ChildPath "winsw.xml"), $bom + $bytes)
}

# 生成服务控制脚本
$startScriptContent = @"
`$extractPath = Split-Path -Parent `$MyInvocation.MyCommand.Path
`$winswExePath = Join-Path `$extractPath 'winsw.exe'

Write-Output "启动服务..."

& `$winswExePath start

Write-Output "服务已启动。"
Read-Host -Prompt "按 Enter 键继续..."
"@

$stopScriptContent = @"
`$extractPath = Split-Path -Parent `$MyInvocation.MyCommand.Path
`$winswExePath = Join-Path `$extractPath 'winsw.exe'

Write-Output "停止服务..."

& `$winswExePath stop

Write-Output "服务已停止。"
Read-Host -Prompt "按 Enter 键继续..."
"@

$uninstallScriptContent = @"
`$extractPath = Split-Path -Parent `$MyInvocation.MyCommand.Path
`$winswExePath = Join-Path `$extractPath 'winsw.exe'

Write-Output "卸载服务..."

if ((& `$winswExePath status) -match 'RUNNING') {
    & `$winswExePath stop
}
& `$winswExePath uninstall

Write-Output "服务已卸载。"
Read-Host -Prompt "按 Enter 键继续..."
"@

$updateScriptContent = @"
`$extractPath = Split-Path -Parent `$MyInvocation.MyCommand.Path
`$winswExePath = Join-Path `$extractPath 'winsw.exe'
`$configFilePath = Join-Path -Path `$extractPath -ChildPath 'deploy_config.json'
`$zipFileName = [System.IO.Path]::GetFileName((Get-Content -Path `$configFilePath | ConvertFrom-Json).DownloadUrl)
`$zipFilePath = Join-Path -Path `$extractPath -ChildPath `$zipFileName
`$appDirName = (Get-Content -Path `$configFilePath | ConvertFrom-Json).AppDirName

Write-Output '正在检查是否有本地部署包...'
if (-Not (Test-Path `$zipFilePath)) {
    Write-Output '正在下载部署包...'
    Invoke-WebRequest -Uri (Get-Content -Path `$configFilePath | ConvertFrom-Json).DownloadUrl -OutFile `$zipFilePath
}

Write-Output '正在停止服务...'
if ((& `$winswExePath status) -match 'RUNNING') {
    & `$winswExePath stop
}

Write-Output '正在解压覆盖应用目录...'
Expand-Archive -Path `$zipFilePath -DestinationPath `$appDirName -Force

Write-Output "部署包已成功解压到 `$appDirName"

Write-Output '正在启动服务...'
& `$winswExePath start

Write-Output "服务已更新。"
Read-Host -Prompt "按 Enter 键继续..."
"@

$startScriptPath = Join-Path -Path $currentScriptPath -ChildPath "start.ps1"
$stopScriptPath = Join-Path -Path $currentScriptPath -ChildPath "stop.ps1"
$uninstallScriptPath = Join-Path -Path $currentScriptPath -ChildPath "uninstall.ps1"
$updateScriptPath = Join-Path -Path $currentScriptPath -ChildPath "update.ps1"

# 将脚本内容写入文件，使用UTF-8 BOM编码
if ($PSVersionTable.PSVersion.Major -ge 6) {
    $startScriptContent | Out-File -FilePath $startScriptPath -Encoding utf8BOM
    $stopScriptContent | Out-File -FilePath $stopScriptPath -Encoding utf8BOM
    $uninstallScriptContent | Out-File -FilePath $uninstallScriptPath -Encoding utf8BOM
    $updateScriptContent | Out-File -FilePath $updateScriptPath -Encoding utf8BOM
} else {
    $scripts = @{
        $startScriptPath = $startScriptContent
        $stopScriptPath = $stopScriptContent
        $uninstallScriptPath = $uninstallScriptContent
        $updateScriptPath = $updateScriptContent
    }

    foreach ($script in $scripts.GetEnumerator()) {
        $bom = [byte[]]@(0xEF, 0xBB, 0xBF)
        $bytes = [System.Text.Encoding]::UTF8.GetBytes($script.Value)
        [System.IO.File]::WriteAllBytes($script.Key, $bom + $bytes)
    }
}

Write-Output "启动脚本已生成: $startScriptPath"
Write-Output "停止脚本已生成: $stopScriptPath"
Write-Output "卸载脚本已生成: $uninstallScriptPath"
Write-Output "更新脚本已生成: $updateScriptPath"

# 设置脚本权限
Set-ExecutionPolicy RemoteSigned -Scope Process -Force

# 执行winsw服务安装
& $winswExePath install

# 提示是否启动服务
$shouldStart = Read-Host "是否启动服务？(Y/N)"
if ($shouldStart.ToUpper() -ne "N") {
    & $winswExePath start
    Write-Output "服务已启动"
    Write-Output "请访问 http://127.0.0.1:$($config.Port)"
} else {
    Write-Output "服务未启动"
}

# 保持脚本窗口打开
Read-Host "按 Enter 键退出..."



